﻿Namespace Imaging

    ''' <summary>Standard Color Temperatures</summary>
    ''' <remarks>Values in Kelvin</remarks>
    Public Enum ColorTemperature

        ''' <summary>2856K</summary><remarks>Stanard illuminant A</remarks>
        CIE_A_K2856_TungstenBulb = 2856

        ''' <summary>2856K</summary><remarks>Stanard illuminant B</remarks>
        CIE_B_K4874_NoonSunlight = 4874

        ''' <summary>6774K</summary><remarks>Stanard illuminant C</remarks>
        CIE_C_K6774_NewNorthSkyDaylight = 6774

        ''' <summary>5003K</summary><remarks>Stanard illuminant D50</remarks>
        CIE_D50_K5000_ClearSkyDaylight = 5003

        ''' <summary>5500K</summary><remarks>Stanard illuminant D55</remarks>
        CIE_D55_K5500_ClearSkyDaylight = 5500

        ''' <summary>6504K</summary><remarks>Stanard illuminant D65</remarks>
        CIE_D65_K6504_NewNorthSkyDaylight = 6504

        ''' <summary>5455K</summary><remarks>Stanard illuminant E</remarks>
        CIE_E_K5455_EqualEenergyRadiator = 5455

        ''' <summary>4200K</summary><remarks>Stanard illuminant F2</remarks>
        CIE_F2_K4200_FluorescentLamp_ = 4200

        ''' <summary>4200K</summary><remarks>Stanard illuminant F2</remarks>
        CIE_F7_K4200_BroadbandFluorescentLamp = 4200

        ''' <summary>2000K</summary><remarks></remarks>
        K2000_CandleLight = 2000

        ''' <summary>2500K</summary><remarks></remarks>
        K2500_Sunrise = 2500

        ''' <summary>5500K</summary><remarks></remarks>
        K5500_ElectronicFlash = 5500

        ''' <summary>7500K</summary><remarks></remarks>
        K7500_ModeratelyOvercastSky = 7500

        ''' <summary>9000K</summary><remarks></remarks>
        K9000_HeavilyOvercastSky = 9000
    End Enum



    Public Class WhitePointTransformer

        Public Shared ReadOnly StandardWP_A As New XYZTriplet(1.0985, 1.0, 0.35585)
        Public Shared ReadOnly StandardWP_B As New XYZTriplet(0.99072, 1.0, 0.85223)
        Public Shared ReadOnly StandardWP_C As New XYZTriplet(0.98074, 1.0, 1.18232)
        Public Shared ReadOnly StandardWP_D50 As New XYZTriplet(0.96422, 1.0, 0.82521)
        Public Shared ReadOnly StandardWP_D55 As New XYZTriplet(0.95682, 1.0, 0.92149)
        Public Shared ReadOnly StandardWP_D65 As New XYZTriplet(0.95047, 1.0, 1.08883)
        Public Shared ReadOnly StandardWP_D75 As New XYZTriplet(0.94972, 1.0, 1.22638)
        Public Shared ReadOnly StandardWP_E As New XYZTriplet(1.0, 1.0, 1.0)
        Public Shared ReadOnly StandardWP_F2 As New XYZTriplet(0.99186, 1.0, 0.67393)
        Public Shared ReadOnly StandardWP_F7 As New XYZTriplet(0.95041, 1.0, 1.08747)
        Public Shared ReadOnly StandardWP_F11 As New XYZTriplet(1.00962, 1.0, 0.6435)

        'Bradford Matrix for conversion from XYZ to cone response domain
        Public ReadOnly _Bradford_M(,) As Double = {{0.8951, 0.2664, -0.1614}, _
                                                          {-0.7502, 1.7135, 0.0367}, _
                                                          {0.0389, -0.0685, 1.0296}}
        'Bradford Matrix for conversion from cone response domain to XYZ
        Public ReadOnly _Bradford_InvertM(,) As Double = {{0.9869929, -0.1470543, 0.1599627}, _
                                                          {0.4323053, 0.5183603, 0.0492912}, _
                                                          {-0.0085287, 0.0400428, 0.9684867}}

        Private _ConversionMatrix_Src2Dst(0 To 2, 0 To 2) As Double
        Private _ConversionMatrix_Dst2Src(0 To 2, 0 To 2) As Double

        Private _SrcWhitePoint As XYZTriplet
        Private _DstWhitePoint As XYZTriplet


        Private Sub CreateConvertionMatrix()
            'Step1: Transform from XYZ into a cone response domain, (ρ, γ, β).
            Dim SrcRho As Double = _Bradford_M(0, 0) * _SrcWhitePoint.X + _Bradford_M(0, 1) * _SrcWhitePoint.Y + _Bradford_M(0, 2) * _SrcWhitePoint.Z
            Dim SrcGamma As Double = _Bradford_M(1, 0) * _SrcWhitePoint.X + _Bradford_M(1, 1) * _SrcWhitePoint.Y + _Bradford_M(1, 2) * _SrcWhitePoint.Z
            Dim SrcBeta As Double = _Bradford_M(2, 0) * _SrcWhitePoint.X + _Bradford_M(2, 1) * _SrcWhitePoint.Y + _Bradford_M(2, 2) * _SrcWhitePoint.Z

            Dim DstRho As Double = _Bradford_M(0, 0) * _DstWhitePoint.X + _Bradford_M(0, 1) * _DstWhitePoint.Y + _Bradford_M(0, 2) * _DstWhitePoint.Z
            Dim DstGamma As Double = _Bradford_M(1, 0) * _DstWhitePoint.X + _Bradford_M(1, 1) * _DstWhitePoint.Y + _Bradford_M(1, 2) * _DstWhitePoint.Z
            Dim DstBeta As Double = _Bradford_M(2, 0) * _DstWhitePoint.X + _Bradford_M(2, 1) * _DstWhitePoint.Y + _Bradford_M(2, 2) * _DstWhitePoint.Z

            'Step2: Scale the vector components by factors dependent upon both the source and destination reference whites.
            Dim Src2DstRho As Double = DstRho / SrcRho
            Dim Src2DstGamma As Double = DstGamma / SrcGamma
            Dim Src2DstBeta As Double = DstBeta / SrcBeta

            Dim Dst2SrcRho As Double = SrcRho / DstRho
            Dim Dst2SrcGamma As Double = SrcGamma / DstGamma
            Dim Dst2SrcBeta As Double = SrcBeta / DstBeta

            'Step3: Create transform matrix using the inverse transform of step 1.
            For i As Integer = 0 To 2
                For j As Integer = 0 To 2
                    _ConversionMatrix_Src2Dst(i, j) = _Bradford_InvertM(i, 0) * Src2DstRho * _Bradford_M(0, j) + _
                                                      _Bradford_InvertM(i, 1) * Src2DstGamma * _Bradford_M(1, j) + _
                                                      _Bradford_InvertM(i, 2) * Src2DstBeta * _Bradford_M(2, j)

                    _ConversionMatrix_Dst2Src(i, j) = _Bradford_InvertM(i, 0) * Dst2SrcRho * _Bradford_M(0, j) + _
                                                      _Bradford_InvertM(i, 1) * Dst2SrcGamma * _Bradford_M(1, j) + _
                                                      _Bradford_InvertM(i, 2) * Dst2SrcBeta * _Bradford_M(2, j)
                Next

            Next




        End Sub

        Public Sub New(ByVal SourceWhitePoint As XYZTriplet, ByVal DestinationWhitePoint As XYZTriplet)
            _SrcWhitePoint = SourceWhitePoint
            _DstWhitePoint = DestinationWhitePoint
            CreateConvertionMatrix()
        End Sub

        Public Property SourceWhitePoint() As XYZTriplet
            Get

            End Get
            Set(ByVal value As XYZTriplet)
                _SrcWhitePoint = value
                CreateConvertionMatrix()
            End Set
        End Property

        Public Property DestinationWhitePoint() As XYZTriplet
            Get

            End Get
            Set(ByVal value As XYZTriplet)
                _DstWhitePoint = value
                CreateConvertionMatrix()
            End Set
        End Property

        Public ReadOnly Property ConversionMatrix_Src2Dst() As Double(,)
            Get
                Return _ConversionMatrix_Src2Dst
            End Get
        End Property

        Public ReadOnly Property ConversionMatrix_Dst2Src() As Double(,)
            Get
                Return _ConversionMatrix_Dst2Src
            End Get
        End Property

        Public Function Convert_Src2Dst(ByVal SourceData As XYZTriplet) As XYZTriplet
            Dim result As XYZTriplet
            result.X = SourceData.X * _ConversionMatrix_Src2Dst(0, 0) + _
                       SourceData.Y * _ConversionMatrix_Src2Dst(0, 1) + _
                       SourceData.Z * _ConversionMatrix_Src2Dst(0, 2)
            result.Y = SourceData.X * _ConversionMatrix_Src2Dst(1, 0) + _
                       SourceData.Y * _ConversionMatrix_Src2Dst(1, 1) + _
                       SourceData.Z * _ConversionMatrix_Src2Dst(1, 2)
            result.Z = SourceData.X * _ConversionMatrix_Src2Dst(2, 0) + _
                       SourceData.Y * _ConversionMatrix_Src2Dst(2, 1) + _
                       SourceData.Z * _ConversionMatrix_Src2Dst(2, 2)
            Return result
        End Function

        Public Function Convert_Dst2Src(ByVal SourceData As XYZTriplet) As XYZTriplet
            Dim result As XYZTriplet
            result.X = SourceData.X * _ConversionMatrix_Dst2Src(0, 0) + _
                       SourceData.Y * _ConversionMatrix_Dst2Src(0, 1) + _
                       SourceData.Z * _ConversionMatrix_Dst2Src(0, 2)
            result.Y = SourceData.X * _ConversionMatrix_Dst2Src(1, 0) + _
                       SourceData.Y * _ConversionMatrix_Dst2Src(1, 1) + _
                       SourceData.Z * _ConversionMatrix_Dst2Src(1, 2)
            result.Z = SourceData.X * _ConversionMatrix_Dst2Src(2, 0) + _
                       SourceData.Y * _ConversionMatrix_Dst2Src(2, 1) + _
                       SourceData.Z * _ConversionMatrix_Dst2Src(2, 2)
            Return result
        End Function




    End Class

End Namespace

